﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include <utility>
#include <typeinfo>

namespace gcmp
{
    namespace anyimpl
    {
        struct bad_any_cast {};
        struct empty_any    {};

        struct IPolicy
        {
            virtual size_t get_size()                                    = 0;
            virtual void   static_delete(void** x)                       = 0;
            virtual void   copy_from_value(void const* src, void** dest) = 0;
            virtual void   clone(void* const* src, void** dest)          = 0;
            virtual void   move(void* const* src, void** dest)           = 0;
            virtual void*  get_value(void** src)                         = 0;
            virtual size_t get_typeid() const                            = 0;
        };

        template<typename T>
        struct SmallValuePolicy_T : IPolicy
        {
            virtual size_t get_size() override                { return sizeof(T); }
            virtual void static_delete(void**)  override      {}
            virtual void copy_from_value(void const* src, void** dest) override { new(dest) T(*reinterpret_cast<T const*>(src)); }
            virtual void clone(void* const* src, void** dest) override { *dest = *src; }
            virtual void move (void* const* src, void** dest) override { *dest = *src; }
            virtual void* get_value(void** src)   override             { return reinterpret_cast<void*>(src); }
            virtual size_t get_typeid() const     override             { return typeid(T).hash_code(); }
        };

        template<typename T>
        struct BigValuePolicy_T : IPolicy
        {
            virtual size_t get_size()          override               { return sizeof(T); }
            virtual void static_delete(void** x)     override         { if (*x) delete(*reinterpret_cast<T**>(x)); *x = NULL; }
            virtual void copy_from_value(void const* src, void** dest) override  { *dest = new T(*reinterpret_cast<T const*>(src)); }
            virtual void clone(void* const* src, void** dest) override{ *dest = new T(**reinterpret_cast<T* const*>(src)); }
            virtual void move(void* const* src, void** dest) override { (*reinterpret_cast<T**>(dest))->~T(); **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src); }
            virtual void* get_value(void** src)          override     { return *src; }
            virtual size_t get_typeid() const            override    { return typeid(T).hash_code(); }
        };

        template<typename T>
        struct choose_policy
        {
            typedef BigValuePolicy_T<T> type;
        };

        template<typename T>
        struct choose_policy<T*>
        {
            typedef SmallValuePolicy_T<T*> type;
        };


        // 为Any的类型选择Policy是非法的， 不应该出现这种情况。 如果出现了， 就会有一个编译错误
        struct Any;
        template<>
        struct choose_policy<Any>
        {
            typedef void type;
        };

        // 一些内建类型的特化
        #define SMALL_POLICY(TYPE) template<> struct choose_policy<TYPE> { typedef SmallValuePolicy_T<TYPE> type; };
        SMALL_POLICY(signed char);
        SMALL_POLICY(unsigned char);
        SMALL_POLICY(signed short);
        SMALL_POLICY(unsigned short);
        SMALL_POLICY(signed int);
        SMALL_POLICY(unsigned int);
        SMALL_POLICY(signed long);
        SMALL_POLICY(unsigned long);
        SMALL_POLICY(float);
        SMALL_POLICY(bool);
        SMALL_POLICY(double);
        SMALL_POLICY(empty_any);
        #undef SMALL_POLICY

        // 返回不同类型的Policy
        template<typename T>
        IPolicy* get_policy()
        {
            static typename choose_policy<T>::type policy;
            return &policy;
        };
    }  // namespace anyimpl

    /// \brief 类Any描述用于任何类型的单个值的类型安全容器。

    /// 这些值类型包括基本数据类型、POD类型、std::string、std::wstring，以及其它正确实现了构造器（拷贝构造、移动构造、拷贝赋值操作符和移动赋值操作符）的单个类对象。
    /// 具体可参见std::any（since C++ 17)的说明
    ///
    /// 1) 类Any的对象存储任何满足构造函数要求的类型的一个实例或为空，而这被称为 any 类对象的状态。存储的实例被称作所含对象。
    ///     若两个状态均为空，或均为非空且其所含对象等价，则两个状态等价。
    /// 2) 非成员 any_cast 函数提供对所含对象的类型安全访问。
    /// 使用：
    ///     Any a = 42;
    ///     cout << a.cast<int>() << endl;
    ///     a = 13;
    ///     cout << a.cast<int>() << endl;
    ///     a = "hello";
    ///     cout << a.cast<const char*>() << endl;
    ///     a = std::string("1234567890");
    ///     cout << a.cast<std::string>() << endl;
    ///     int n = 42;
    ///     a = &n;
    ///     cout << *a.cast<int*>() << endl;
    ///     Any b = true;
    ///     cout << b.cast<bool>() << endl;
    ///     swap(a, b);
    ///     cout << a.cast<bool>() << endl;
    ///     a.cast<bool>() = false;
    ///     cout << a.cast<bool>() << endl;
    ///
    /// \see https://en.cppreference.com/w/cpp/utility/any
    struct Any
    {
    public:
        /// \brief 构造函数
        /// \param x 所含对象
        template <typename T>
        Any(const T& x)
            : m_Policy(anyimpl::get_policy<anyimpl::empty_any>())
            , m_Value(NULL)
        {
            assign(x);
        }

        /// \brief 构造函数，构造空的Any对象
        Any()
            : m_Policy(anyimpl::get_policy<anyimpl::empty_any>()), m_Value(NULL)
        { }

        /// \brief 构造函数，构造字符串Any对象
        Any(const char* x)
            : m_Policy(anyimpl::get_policy<anyimpl::empty_any>()), m_Value(NULL)
        {
            assign(x);
        }

        /// \brief 拷贝构造函数
        Any(const Any& x)
            : m_Policy(anyimpl::get_policy<anyimpl::empty_any>()), m_Value(NULL)
        {
            assign(x);
        }

        /// \brief 移动构造函数
        Any(Any&& x)
            : m_Policy(anyimpl::get_policy<anyimpl::empty_any>()), m_Value(NULL)
        {
            assign(x);
        }

        /// \brief 析构函数
        ~Any() {
            m_Policy->static_delete(&m_Value);
        }

        /// \brief 赋值
        /// \param x Any对象
        /// \return Any& 结果Any对象
        Any& assign(const Any& x) {
            reset();
            m_Policy = x.m_Policy;
            m_Policy->clone(&x.m_Value, &m_Value);
            return *this;
        }

        /// \brief 赋值
        /// \param x 所含对象
        /// \return Any& 结果Any对象，即自己
        template <typename T>
        Any& assign(const T& x) {
            reset();
            m_Policy = anyimpl::get_policy<T>();
            m_Policy->copy_from_value(&x, &m_Value);
            return *this;
        }

        /// \brief 重载=操作符
        /// \param x 所含对象
        /// \return Any& 结果Any对象，即自己
        template<typename T>
        Any& operator=(const T& x) {
            return assign(x);
        }

        /// \brief 重载=操作符
        /// \param x Any对象
        /// \return Any& 结果Any对象，即自己
        Any& operator=(const Any& x) {
            return assign(x);
        }

        /// \brief 重载=操作符
        /// \param x Any对象
        /// \return Any& 结果Any对象，即自己
        Any& operator=(Any&& x) {
            return assign(x);
        }

        /// \brief 重载=操作符
        /// \param x 所含对象字符串
        /// \return Any& 结果Any对象，即自己
        Any& operator=(const char* x) {
            return assign(x);
        }

        /// \brief 交换
        /// \param x 交换对象
        /// \return Any& 交换后的Any对象
        Any& swap(Any& x) {
            std::swap(m_Policy, x.m_Policy);
            std::swap(m_Value, x.m_Value);
            return *this;
        }

        /// \brief Cast操作符转换成所含对象
        /// \return T & 所含对象
        template<typename T>
        T& cast() {
            if (!policy_compatible(anyimpl::get_policy<T>()))
                throw anyimpl::bad_any_cast();
            T* r = reinterpret_cast<T*>(m_Policy->get_value(&m_Value));
            return *r;
        }

        /// \brief Cast操作符转换成所含对象
        /// \return const T & 所含对象
        template<typename T>
        const T& cast() const {
            if (!policy_compatible(anyimpl::get_policy<T>()))
                throw anyimpl::bad_any_cast();
            const T* r = reinterpret_cast<const T*>(m_Policy->get_value(const_cast<void **>(&m_Value)));
            return *r;
        }

        /// \brief 是否为空
        /// \return bool 为空返回true
        bool empty() const {
            return policy_compatible(anyimpl::get_policy<anyimpl::empty_any>());
        }

        /// \brief 释放内存
        void reset() {
            m_Policy->static_delete(&m_Value);
            m_Policy = anyimpl::get_policy<anyimpl::empty_any>();
        }

        /// \brief 是否兼容
        /// \param x Any对象
        /// \return true 如果类型一样， 返回true
        bool compatible(const Any& x) const {
            return policy_compatible(x.m_Policy);
        }

    private:
        bool policy_compatible(const anyimpl::IPolicy *pPolicy) const
        {
            return m_Policy == pPolicy ||
                   m_Policy->get_typeid() == pPolicy->get_typeid();
        }
        anyimpl::IPolicy* m_Policy;
        void*             m_Value;
    };  // struct any
} // namespace gcmp
